package org.grayrabbit.cms.plugin.servlet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public abstract class BaseFileServerServlet extends HttpServlet {
	private static final long serialVersionUID = -8874104981755406800L;

	public static final String PATH_SEPARATOR = "/";
	public static final String RESOURCE_URL_PREFIX = "resources";
	private static List<Class<? extends DownloadStrategy>> downloadStrategies = Collections.synchronizedList(new ArrayList<Class<? extends DownloadStrategy>>());
	private static Logger log = LoggerFactory.getLogger(BaseFileServerServlet.class);
	public static String SERVLET_PATH;

	public void init(ServletConfig servletConfig) throws ServletException {
		super.init(servletConfig);
	}

	public String getMimeType(File fileToServe) {
		return getServletContext().getMimeType(fileToServe.getAbsolutePath());
	}

	public abstract String getDecodedPathInfo(HttpServletRequest paramHttpServletRequest);

	protected abstract DownloadStrategy instantiateDownloadStrategy(Class<? extends DownloadStrategy> paramClass);

	public abstract String urlDecode(String paramString);

	protected abstract String getContentType(String paramString);

	protected void doGet(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws ServletException,
			IOException {
		try {
			DownloadStrategy downloadStrategy = getDownloadStrategy(httpServletRequest);
			if (downloadStrategy != null) {
				downloadStrategy.serveFile(this, httpServletRequest,httpServletResponse);
			} else {
				httpServletResponse.sendError(404,"The file you were looking for was not found");
			}
		} catch (Throwable t) {
			log.info("Error while serving file ", t);
			throw new ServletException(t);
		}
	}

	protected void addDownloadStrategy(Class<? extends DownloadStrategy> strategyClass) {
		downloadStrategies.add(strategyClass);
	}

	private DownloadStrategy getDownloadStrategy(HttpServletRequest httpServletRequest) {
		String url = httpServletRequest.getRequestURI().toLowerCase();
		for (Class<? extends DownloadStrategy> downloadStrategyClass : downloadStrategies) {
			DownloadStrategy downloadStrategy = instantiateDownloadStrategy(downloadStrategyClass);
			if (downloadStrategy.matches(url)) {
				return downloadStrategy;
			}
		}
		return null;
	}

	static {
		downloadStrategies.add(PluginResourceDownload.class);
		SERVLET_PATH = "download";
	}
}
